import consul
import requests
from fastapi import Request, HTTPException
from functools import wraps

from config import settings

"""
认证鉴权中间件
from fastapi import FastAPI
app = FastAPI()

@app.get("/protected")
@auth_required(required_permissions=["read_data"])
def protected_route(request: Request):
    return {"message": "认证鉴权通过，访问成功"}
"""


def auth_required(required_permissions=None):
    if required_permissions is None:
        required_permissions = []
    auth_middleware = ConsulAuthMiddleware()

    def decorator(func):
        @wraps(func)
        async def wrapper(request: Request, *args, **kwargs):
            token = request.headers.get('Authorization')
            if not token:
                raise HTTPException(status_code=401, detail="未提供认证令牌")
            try:
                user_info = auth_middleware.authenticate(token)
                if not auth_middleware.authorize(user_info, required_permissions):
                    raise HTTPException(status_code=403, detail="权限不足")
                return await func(request, *args, **kwargs)
            except HTTPException:
                raise
            except Exception as e:
                raise HTTPException(status_code=500, detail="认证鉴权过程中发生错误") from e

        return wrapper

    return decorator


class ConsulAuthMiddleware:
    def __init__(self, consul_host=settings.consul_host, consul_port=settings.consul_port,
                 auth_service_name='auth-service'):
        self.consul_client = consul.Consul(host=consul_host, port=consul_port)
        self.auth_service_name = auth_service_name

    def _get_auth_service_url(self):
        services = self.consul_client.catalog.service(self.auth_service_name)[1]
        if not services:
            raise Exception(f"未找到 {self.auth_service_name} 服务")
        service = services[0]
        return f"http://{service['ServiceAddress']}:{service['ServicePort']}"

    def authenticate(self, token):
        auth_url = self._get_auth_service_url()
        try:
            response = requests.post(f"{auth_url}/verify", json={{"token": token}})
            response.raise_for_status()
            return response.json()
        except requests.exceptions.RequestException as e:
            raise HTTPException(status_code=500, detail="认证服务调用失败") from e

    def authorize(self, user_info, required_permissions):
        if not required_permissions:
            return True
        auth_url = self._get_auth_service_url()
        try:
            response = requests.post(
                f"{auth_url}/authorize",
                json={{"user_info": user_info, "permissions": required_permissions}}
            )
            response.raise_for_status()
            return response.json().get('authorized', False)
        except requests.exceptions.RequestException as e:
            raise HTTPException(status_code=500, detail="鉴权服务调用失败") from e
